package com.xzzz.irda.guardcat.server.repos.mysql;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xzzz.common.base.util.DateUtils;
import com.xzzz.irda.guardcat.server.app.pojo.MachineInfo;
import com.xzzz.irda.guardcat.server.metric.MetricRepository;
import com.xzzz.irda.guardcat.server.repos.mysql.mappers.JmmMapper;
import com.xzzz.irda.guardcat.server.repos.mysql.pojo.JmmMySQLEntity;
import com.xzzz.irda.guardcat.server.metric.memory.JmmInfo;
import com.xzzz.irda.tracker.core.adapter.aspect.TrackerStart;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author xzzz
 */
@Slf4j
public class JmmRepositoryInMySQL extends MetricRepository<JmmInfo> {


    @Autowired
    private JmmMapper jmmMapper;

    @Override
    public void save(MachineInfo machineInfo, JmmInfo jmmInfo) {
        JmmMySQLEntity entity = new JmmMySQLEntity();
        entity.setHi(jmmInfo.getHeapUsage().getInitValue());
        entity.setHm(jmmInfo.getHeapUsage().getMaxValue());
        entity.setHc(jmmInfo.getHeapUsage().getCommittedValue());
        entity.setHu(jmmInfo.getHeapUsage().getUsedValue());
        entity.setNhi(jmmInfo.getNonHeapUsage().getInitValue());
        entity.setNhm(jmmInfo.getNonHeapUsage().getMaxValue());
        entity.setNhc(jmmInfo.getNonHeapUsage().getCommittedValue());
        entity.setNhu(jmmInfo.getNonHeapUsage().getUsedValue());
        entity.setMi(jmmInfo.getMetaspaceUsage().getInitValue());
        entity.setMm(jmmInfo.getMetaspaceUsage().getMaxValue());
        entity.setMc(jmmInfo.getMetaspaceUsage().getCommittedValue());
        entity.setMu(jmmInfo.getMetaspaceUsage().getUsedValue());
        entity.setEi(jmmInfo.getEdenSpace().getInitValue());
        entity.setEm(jmmInfo.getEdenSpace().getMaxValue());
        entity.setEc(jmmInfo.getEdenSpace().getCommittedValue());
        entity.setEu(jmmInfo.getEdenSpace().getUsedValue());
        entity.setSi(jmmInfo.getSurvivorSpace().getInitValue());
        entity.setSm(jmmInfo.getSurvivorSpace().getMaxValue());
        entity.setSc(jmmInfo.getSurvivorSpace().getCommittedValue());
        entity.setSu(jmmInfo.getSurvivorSpace().getUsedValue());
        entity.setOi(jmmInfo.getOldGen().getInitValue());
        entity.setOm(jmmInfo.getOldGen().getMaxValue());
        entity.setOc(jmmInfo.getOldGen().getCommittedValue());
        entity.setOu(jmmInfo.getOldGen().getUsedValue());

        entity.setCci(jmmInfo.getCodeCacheUsage().getInitValue());
        entity.setCcm(jmmInfo.getCodeCacheUsage().getMaxValue());
        entity.setCcc(jmmInfo.getCodeCacheUsage().getCommittedValue());
        entity.setCcu(jmmInfo.getCodeCacheUsage().getUsedValue());
        entity.setCcsi(jmmInfo.getCompressedClassSpace().getInitValue());
        entity.setCcsm(jmmInfo.getCompressedClassSpace().getMaxValue());
        entity.setCcsc(jmmInfo.getCompressedClassSpace().getCommittedValue());
        entity.setCcsu(jmmInfo.getCompressedClassSpace().getUsedValue());

        entity.setCreTime(DateUtils.parse(jmmInfo.getCreTime()));
        entity.setAppName(machineInfo.getAppName());
        entity.setMachineId(machineInfo.getMachineId());
        jmmMapper.insert(entity);
    }

    @Override
    @TrackerStart
    @Scheduled(cron = "0 0/1 * * * ?")
    public void expire() {
        long start = System.currentTimeMillis();
        Date today = DateUtil.date();
        // 删除1天前的
        Date expireDate = DateUtil.offsetDay(today, -1);
        String expireDateStr = DateUtil.format(expireDate, "yyyy-MM-dd HH:mm:ss");

        QueryWrapper<JmmMySQLEntity> query = new QueryWrapper<>();
        query.le("cre_time", expireDate);
        int num = jmmMapper.delete(query);
        log.info("[GUARDCAT] 删除小于 [{}] JMM  信息, 共:[{}], 用时: {}", expireDateStr, num, System.currentTimeMillis() - start);
    }

    @Override
    public JmmInfo getByMachineId(String machineId) {
        QueryWrapper<JmmMySQLEntity> where = new QueryWrapper<>();
        where.eq("machine_id", machineId)
                .orderByDesc("cre_time")
                .last("limit 1");
        return entityTo(jmmMapper.selectOne(where));
    }

    @Override
    public List<JmmInfo> listByMachineId(String machineId) {
        QueryWrapper<JmmMySQLEntity> where = new QueryWrapper<>();
        where.eq("machine_id", machineId)
                .orderByDesc("cre_time");

        List<JmmMySQLEntity> entities = jmmMapper.selectList(where);
        if (CollUtil.isEmpty(entities)) {
            return new ArrayList<>();
        }

        List<JmmInfo> jmms = new ArrayList<>();
        for (JmmMySQLEntity entity : entities) {
            jmms.add(entityTo(entity));
        }
        return jmms;
    }

    @Override
    public List<JmmInfo> list(MachineInfo machineInfo, JmmInfo jmmInfo, Map<String, Object> args) {
        QueryWrapper<JmmMySQLEntity> where = new QueryWrapper<>();
        where.eq("machine_id", machineInfo.getMachineId())
                .orderByDesc("cre_time")
                .last("limit 720")
        ;

        List<JmmMySQLEntity> entities = jmmMapper.selectList(where);
        if (CollUtil.isEmpty(entities)) {
            return new ArrayList<>();
        }

        List<JmmInfo> jmms = new ArrayList<>();
        for (JmmMySQLEntity entity : entities) {
            jmms.add(entityTo(entity));
        }

        return jmms;
    }

    private JmmInfo entityTo(JmmMySQLEntity entity) {
        if (entity == null) {
            return null;
        }

        JmmInfo jmmInfo = new JmmInfo();
        JmmInfo.UsageInfo heapUsage = new JmmInfo.UsageInfo();
        JmmInfo.UsageInfo nonHeapUsage = new JmmInfo.UsageInfo();
        JmmInfo.UsageInfo metaspaceUsage = new JmmInfo.UsageInfo();
        JmmInfo.UsageInfo edenSpace = new JmmInfo.UsageInfo();
        JmmInfo.UsageInfo survivorSpace = new JmmInfo.UsageInfo();
        JmmInfo.UsageInfo oldGen = new JmmInfo.UsageInfo();

        JmmInfo.UsageInfo codeCacheUsage = new JmmInfo.UsageInfo();
        JmmInfo.UsageInfo compressedClassSpace = new JmmInfo.UsageInfo();

        heapUsage.setInitValue(entity.getHi());
        heapUsage.setMaxValue(entity.getHm());
        heapUsage.setCommittedValue(entity.getHc());
        heapUsage.setUsedValue(entity.getHu());

        nonHeapUsage.setInitValue(entity.getNhc());
        nonHeapUsage.setMaxValue(entity.getNhm());
        nonHeapUsage.setCommittedValue(entity.getNhc());
        nonHeapUsage.setUsedValue(entity.getNhu());

        metaspaceUsage.setInitValue(entity.getMi());
        metaspaceUsage.setMaxValue(entity.getMm());
        metaspaceUsage.setCommittedValue(entity.getMc());
        metaspaceUsage.setUsedValue(entity.getMu());

        edenSpace.setInitValue(entity.getEi());
        edenSpace.setMaxValue(entity.getEm());
        edenSpace.setCommittedValue(entity.getEc());
        edenSpace.setUsedValue(entity.getEu());

        survivorSpace.setInitValue(entity.getSi());
        survivorSpace.setMaxValue(entity.getSm());
        survivorSpace.setCommittedValue(entity.getSc());
        survivorSpace.setUsedValue(entity.getSu());

        oldGen.setInitValue(entity.getOi());
        oldGen.setMaxValue(entity.getOm());
        oldGen.setCommittedValue(entity.getOc());
        oldGen.setUsedValue(entity.getOu());

        codeCacheUsage.setInitValue(entity.getCci());
        codeCacheUsage.setMaxValue(entity.getCcm());
        codeCacheUsage.setCommittedValue(entity.getCcc());
        codeCacheUsage.setUsedValue(entity.getCcu());

        compressedClassSpace.setInitValue(entity.getCcsi());
        compressedClassSpace.setMaxValue(entity.getCcsm());
        compressedClassSpace.setCommittedValue(entity.getCcsc());
        compressedClassSpace.setUsedValue(entity.getCcsu());

        jmmInfo.setHeapUsage(heapUsage);
        jmmInfo.setNonHeapUsage(nonHeapUsage);
        jmmInfo.setMetaspaceUsage(metaspaceUsage);
        jmmInfo.setEdenSpace(edenSpace);
        jmmInfo.setSurvivorSpace(survivorSpace);
        jmmInfo.setOldGen(oldGen);
        jmmInfo.setCodeCacheUsage(codeCacheUsage);
        jmmInfo.setCompressedClassSpace(compressedClassSpace);

        jmmInfo.setCreTime(DateUtils.toYMDHMS(entity.getCreTime()));
        return jmmInfo;
    }

}
